package com.axter.chrome.bookmark;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.axter.chrome.TemplateUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 书签分析
 * Created by zhaobo on 2017/7/28.
 */
public class BookmarkAnalysis {
    public static void main(String[] args) {
//        chongfu("C:\\Users\\zhaobo\\OneDrive\\Desktop\\bookmarks_2017_7_28_1.html");
//
//        String left = "C:\\Users\\zhaobo\\OneDrive\\Desktop\\bookmarks_2017_8_23_2.html";
//        String right = "C:\\Users\\zhaobo\\OneDrive\\Desktop\\bookmarks_2017_8_31.html";
//        System.out.println(compareLeftAndRight(left, right));

//        chongfuHTML("C:\\Users\\zhaobo\\OneDrive\\Desktop\\bookmarks_2017_8_31.html");
    }

    // =============================================================
    // 左边没有右边的
    // =============================================================

    /**
     * 比较左右两边的html
     *
     * @param left
     * @param right
     * @return
     */
    public static String compareLeftAndRight(String left, String right) {
        StringBuilder result = new StringBuilder();
        StringBuilder sb = new StringBuilder();

        Bookmark leftBookmark = getBookmarks(left);
        Bookmark rightBookmark = getBookmarks(right);
        List<Bookmark> leftUrls = getUrls(leftBookmark);
        List<Bookmark> rightUrls = getUrls(rightBookmark);
        int cc = 0;
        for (int i = 0, ii = rightUrls.size(); i < ii - 1; i++) {
            boolean ishave = false;
            for (int j = 0, jj = leftUrls.size(); j < jj; j++) {
                if (leftUrls.get(j).equals(rightUrls.get(i))) {
                    ishave = true;
                    break;
                }
            }
            if (!ishave) {
                cc++;
                sb.append("左边不存在: ");
                sb.append(rightUrls.get(i).getFullPath());
                sb.append('\n');
            }
        }
        result.append("不存在");
        result.append(cc);
        result.append("个url");
        result.append('\n');
        result.append(sb);
        return result.toString();
    }

    // =============================================================
    // =============================================================

    /**
     * 去除重复书签后,导出书签到文件
     *
     * @param htmlPath html地址
     * @return
     */
    public static String exportBookmarkToHtmlFile(String htmlPath) {
        Bookmark root = getBookmarks(htmlPath);
        List<Bookmark> urls = getUrls(root);
        List<Bookmark> chongfu = new ArrayList<>();
        for (int i = 0, count = urls.size(); i < count - 1; i++) {
            for (int j = i + 1; j < count; j++) {
                if (urls.get(i).equals(urls.get(j))) {
                    chongfu.add(urls.get(j));
                    break;
                }
            }
        }
        for (int i = chongfu.size() - 1; i >= 0; i--) {
            Bookmark parent = chongfu.get(i).getParent();
            if (parent != null && parent.getChildren() != null) {
                parent.getChildren().remove(chongfu.get(i));
            }
        }

        try {
            TemplateUtils.getBootmarks2(getBookmarkLabel(root, 0));
        } catch (Exception e) {
            e.printStackTrace();
            return "导出出错\t" + e.getMessage();
        }
        return "导出成功";
    }

    /**
     * 根据书签目录or链接生成相应html标签
     *
     * @param bookmark
     * @param tab
     * @return
     */
    private static String getBookmarkLabel(Bookmark bookmark, int tab) {
        StringBuilder sb = new StringBuilder();
        if (bookmark.getType() == Bookmark.TYPE_DIR) {
            sb.append(getTabStr(tab));
            sb.append("<DT><H3 ");
            for (Map.Entry<String, String> entry : bookmark.getAttrs().entrySet()) {
                sb.append(entry.getKey());
                sb.append("=\"");
                sb.append(entry.getValue());
                sb.append("\" ");
            }
            sb.append(">");
            sb.append(bookmark.getTitle());
            sb.append("</H3>");
            sb.append('\n');

            if (bookmark.getChildren() != null && bookmark.getChildren().size() > 0) {
                sb.append(getTabStr(tab));
                sb.append("<DL><p>");
                sb.append('\n');
                for (Bookmark c : bookmark.getChildren()) {
                    sb.append(getBookmarkLabel(c, tab + 4));
                }
                sb.append('\n');
                sb.append("</DL><p>");
                sb.append('\n');
            }
        } else if (bookmark.getType() == Bookmark.TYPE_URL) {
            sb.append(getTabStr(tab));
            sb.append("<DT>");
            sb.append("<A ");
            for (Map.Entry<String, String> entry : bookmark.getAttrs().entrySet()) {
                sb.append(entry.getKey());
                sb.append("=\"");
                sb.append(entry.getValue());
                sb.append("\" ");
            }
            sb.append(">");
            sb.append(bookmark.getTitle());
            sb.append("</A>");
            sb.append('\n');
        }
        return sb.toString();
    }


    /**
     * 根据数目返回空格字符串
     *
     * @param tab
     * @return
     */
    private static String getTabStr(int tab) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < tab; i++) {
            sb.append(" ");
        }
        return sb.toString();
    }


    // =============================================================
    // =============================================================

    /**
     * 检测重复的url
     *
     * @param path
     * @return
     */
    public static String checkRepeatUrls(String path) {
        StringBuilder result = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        List<Bookmark> urls = getUrls(getBookmarks(path));
        int cc = 0;
        for (int i = 0, count = urls.size(); i < count - 1; i++) {
            for (int j = i + 1; j < count; j++) {
                if (urls.get(i).equals(urls.get(j))) {
                    cc++;
                    sb.append(urls.get(i).getTitle());
                    sb.append('\n');
                }
            }
        }
        result.append("共");
        result.append(cc);
        result.append("个相同url");
        result.append('\n');
        result.append(sb);
        return result.toString();
    }

    /**
     * 获取跟Bookmark下的所有链接
     *
     * @param root
     * @return
     */
    public static List<Bookmark> getUrls(Bookmark root) {
        List<Bookmark> urls = new ArrayList<Bookmark>();
        getUrls(root, urls);
        return urls;
    }

    private static void getUrls(Bookmark root, List<Bookmark> urls) {
        if (root.getType() == Bookmark.TYPE_DIR && root.getChildren() != null && root.getChildren().size() > 0) {
            for (Bookmark bookmark : root.getChildren()) {
                getUrls(bookmark, urls);
            }
        } else {
            urls.add(root);
        }
    }

    // =============================================================
    // =============================================================


    /**
     * 解析Bookmark
     *
     * @param html html路径
     * @return
     */
    public static Bookmark getBookmarks(String html) {
        try {
            Document doc = Jsoup.parse(new File(html), "UTF-8");
            Element dl = doc.select("dl").first();
            Bookmark bookmark = new Bookmark();
            bookmark.setTitle("root");
            bookmark.setType(Bookmark.TYPE_DIR);
            getBookmark(dl.child(1), bookmark);
            return bookmark;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * dl为起点  dt>h3为目录,目录下面可能为目录或者url
     *
     * @param dl
     * @param parent
     */
    private static void getBookmark(Element dl, Bookmark parent) {
        Element rdl = null;
        String rtitle = null;
        String rurl = null;
        String rurlTitle = null;
        TreeMap<String, String> attrs = new TreeMap<>();
        Elements dts = dl.children();
        // 大目录下有很多小目录的特殊情况
        if (dts.first().tagName().equals("p") && dts.first().text().trim().equals("")) {
            for (int i = 1, count = dts.size(); i < count; i++) {
                getBookmark(dts.get(i), parent);
            }
            return;
        }
        for (Element dt : dts) {
            if (dt.tagName().equals("h3")) {// 目录
                rtitle = dt.text();
                attrs.clear();
                Iterator<Attribute> iterator = dt.attributes().iterator();
                while (iterator.hasNext()) {
                    Attribute obj = iterator.next();
                    attrs.put(obj.getKey().toUpperCase(), obj.getValue());
                }
            } else if (dt.tagName().equals("a")) {// 超链接
                rurl = dt.attr("href");
                rurlTitle = dt.text();
                attrs.clear();
                Iterator<Attribute> iterator = dt.attributes().iterator();
                while (iterator.hasNext()) {
                    Attribute obj = iterator.next();
                    attrs.put(obj.getKey().toUpperCase(), obj.getValue());
                }
            } else if (dt.tagName().equals("dl")) {
                rdl = dt;
            }
        }

        Bookmark result = new Bookmark();
        if (rtitle != null && rtitle.length() > 0) {
            result.setType(Bookmark.TYPE_DIR);
            result.setTitle(rtitle);
            result.setParent(parent);
            result.setAttrs(attrs);
            if (attrs.containsKey("PERSONAL_TOOLBAR_FOLDER") && "true".equals(attrs.get("PERSONAL_TOOLBAR_FOLDER"))) {
                parent.setType(result.getType());
                parent.setTitle(result.getTitle());
                parent.setAttrs(result.getAttrs());
                if (rdl != null) {
                    getBookmark(rdl, parent);
                    return;
                }
            } else {
                parent.addBookmark(result);
            }
        } else {
            result.setType(Bookmark.TYPE_URL);
            result.setTitle(rurlTitle);
            result.setUrl(rurl);
            result.setAttrs(attrs);
            result.setParent(parent);
            parent.addBookmark(result);
        }
        if (rdl != null) {
            getBookmark(rdl, result);
        }
    }
}
